package com.trafficsys.modules.loginAndRegister.service.impl;

import com.trafficsys.modules.entity.*;
import com.trafficsys.modules.loginAndRegister.dao.*;
import com.trafficsys.modules.loginAndRegister.service.PoliceService;
import com.trafficsys.modules.loginAndRegister.util.MD5Util;
import com.trafficsys.modules.loginAndRegister.util.RedisUtils;
import com.trafficsys.modules.loginAndRegister.util.SmsSend;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicInteger;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @Author Zhao Bin
 * @Date 2021/9/28 13:14
 * @Version 1.0
 */
@Service
public class PoliceServiceImpl implements PoliceService {
    @Autowired
    DriveCardDao driveCardDao;
    @Autowired
    PoliceDao policeDao;
    @Autowired
    TravelCardDao travelCardDao;
    @Autowired(required = false)
    private MyNodeDao myNodeDao;//获取权限
    @Autowired
    MD5Util md5Util;
    @Autowired
    private StringRedisTemplate redisTemplate;
    //时间间隔  错误后间隔1分钟后再试
    private static final int TIME_INTERVAL = 1;
    //登录失败重试次数上限制 3次后锁定
    private static final int FAILED_RETRY_TIMES = 3;
    // redis 记录用户登录失败次数key
    private static final String LOGIN_FAILED_COUNT ="LOGIN:FAILED:COUNT:";
    /**
     * 根据key获取计数器
     */
    private RedisAtomicInteger getRedisCounter(String key){
        RedisAtomicInteger counter=
                new RedisAtomicInteger(key,redisTemplate.getConnectionFactory());
        if(counter.get() == FAILED_RETRY_TIMES){
            counter.expire(TIME_INTERVAL, TimeUnit.MINUTES);
        }
        return counter;
    }
    /*********************************************   以下管理员功能  *********************************************************
     * /添加驾驶证方法   管理员功能
     * @param driveCard
     * @return
     */
    @Override
    public HashMap<String, Object> addDriveCard(DriveCard driveCard) {
        HashMap<String,Object> map= new HashMap<>();
        //设置当前时间为发证日期
        Timestamp crateDate = new Timestamp(new Date().getTime());
        driveCard.setCreateDate(crateDate);
        //设置有效期
        Date endDate=new Date();
        endDate.setYear(endDate.getYear()+6);//有效期为6年
        Timestamp validPeriod=new Timestamp(endDate.getTime());
        driveCard.setValidPeriod(validPeriod);
        //添加到数据库
        int n=0;
        try {
            n=driveCardDao.insert(driveCard);
        }catch (Exception e){
            e.printStackTrace();
            map.put("info","该驾驶证号已存在");
            return map;
        }
        if(n>=1){
            map.put("info","添加成功");
        }else{
            map.put("info","添加失败");
        }
        return map;
    }
    /**
     * 添加行驶证方法   管理员功能
     * @param travelCard
     * @return
     */
    @Override
    public HashMap<String, Object> addTravelCard(TravelCard travelCard) {
        HashMap<String,Object> map= new HashMap<>();
        //设置行驶证有效期
        Date endDate=new Date();
        endDate.setYear(endDate.getYear()+10);//有效期为10年
        Timestamp validPeriod=new Timestamp(endDate.getTime());
        travelCard.setInvalidDate(validPeriod);
        int n=0;
        try {
            n=travelCardDao.insert(travelCard);
        }catch (Exception e){
            e.printStackTrace();
            map.put("info","该行驶证号已存在");
            return map;
        }
        if(n>=1){
            map.put("info","添加成功");
        }else{
            map.put("info","添加失败");
        }
        return map;
    }
    /**
     * 警员登录    管理员功能
     * @param police
     * @return
     */
    @Override
    public HashMap<String, Object> policeLogin(Police police) {
        HashMap<String,Object> map= new HashMap<>();
        Police police1;
        String key;
        //根据登录方式 获取相应的错误登录次数
        if(police.getCardId() != null){
            key=LOGIN_FAILED_COUNT + police.getCardId();
        }else{
            key=LOGIN_FAILED_COUNT + police.getPhone();
        }
        RedisAtomicInteger counter=getRedisCounter(key);
        //检测错误登录次数 大于上限则锁定一分钟
        if(counter.get() >=FAILED_RETRY_TIMES){
            map.put("info","登录失败次数已达上限，请1分钟后再试！");
            return map;
        }
        //登陆密码 加密处理
        String password=md5Util.getMD5(police.getPassword());
        if(police.getCardId() != null){//身份证号码登录
            String cardId=police.getCardId();
            police1=policeDao.loginByCardId(cardId,password);
        }else{//电话号码登录
            String phone=police.getPhone();
            police1=policeDao.loginByPhone(phone,password);
        }
        //验证登录是否成功
        if(police1 != null){
            //登录成功后将key删除
            redisTemplate.delete(key);
            map.put("info","登录成功");
            map.put("police",police1);
        }else{
            counter.getAndIncrement();
            map.put("info","您已经登录失败"+counter+"次！！");
        }
        return map;
    }

    /**
     *  添加警员方法   管理员功能
     */
    @Override
    public HashMap<String, Object> addPolice(Police police) {
        HashMap<String,Object> map=new HashMap<>();
        int n=0;
        try {
            //密码使用MD5加密加盐
            police.setPassword(md5Util.getMD5(police.getPassword()));
            n=policeDao.insert(police);
        }catch (Exception e){
            e.printStackTrace();
            map.put("info","该身份证或电话号码已被注册");
            return map;
        }
        if(n>=1){//注册成功
            map.put("info","添加成功");
        }else{
            map.put("info","添加失败");
        }
        return map;
    }

    @Override
    public HashMap<String, Object> getPoliceByPhone(String phone) {
        HashMap<String,Object> map=new HashMap<>();
        Police police=policeDao.getPoliceByPhone(phone);
        map.put("police",police);
        return map;
    }
    /**
     * 获取权限
     */
    @Override
    public HashMap<String, Object> policeSelectPower(String cardId) {
        HashMap<String,Object> map=new HashMap<>();
        List<MyNode> list=myNodeDao.policeSelectPower(cardId);
        List<MyNode> powerList=new ArrayList<>();
        if (list!=null){
            //构建权限菜单的数据结构
            for (MyNode one:list){
                if (one.getParentId()==0){
                    //ParentId为0 则有子菜单  非零则 没有子菜单
                    MyNode mn=new MyNode();
                    mn.setUrl(one.getUrl());
                    mn.setIndex(one.getIndex());
                    mn.setName(one.getName());
                    System.out.println(one.getName().toString());
                    //创建一个集合
                    List<MyNode> listChildren=new ArrayList<>();
                    //遍历 父节点等于上面子节点的Node 则为上面的菜单的子菜单
                    for(MyNode two:list){
                        if (two.getParentId()==one.getNodeId()){
                            listChildren.add(two);
                            System.out.println(two.getName().toString());
                        }
                    }
                    //将父菜单的子菜单 装入父菜单的子菜单集合list
                    mn.setChildren(listChildren);
                    powerList.add(mn);
                }
            }
        }
        map.put("powerList",powerList);
        return map;
    }
}
